using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace IFIGame
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class Movable : Microsoft.Xna.Framework.DrawableGameComponent
    {
        protected int x;
        protected int y;
        protected int v;
        protected float rotationAngle;
        Vector2 origin;
        protected Texture2D texture;
        SpriteBatch spriteBatch;

        public Movable(Game game)
            : base(game)
        {
            // TODO: Construct any child components here
        }

        public Movable(Game game, int _x, int _y, string _stringTexture)
            : base(game)
        {
            this.x = _x;
            this.y = _y;
            this.texture = game.Content.Load<Texture2D>(_stringTexture);
            origin.X = texture.Width / 2;
            origin.Y = texture.Height / 2;
            this.spriteBatch = new SpriteBatch(game.GraphicsDevice);
        }

        public Movable(Game game, int _x, int _y, int _v, string _stringTexture):base(game)
        {
            this.x = _x;
            this.y = _y;
            this.v = _v;
            this.texture = game.Content.Load<Texture2D>(_stringTexture);
            rotationAngle = 0;
            origin.X = texture.Width / 2;
            origin.Y = texture.Height / 2;
            this.spriteBatch = new SpriteBatch(game.GraphicsDevice);
        }


        public void gotoXY(int _x, int _y)
        {
            int dx = _x - this.x;
            int dy = _y - this.y;
            double len, sin, cos, angle;
            if (dx == 0)
            {
                cos = 0;
                sin = 1;
                if (dy < 0)
                    sin = -1;
            }
            else
            {
                len = Math.Sqrt(dy * dy + dx * dx);
                angle = Math.Acos(dx / len);
                if (dy < 0)
                    angle = -angle;
                cos = Math.Cos(angle);
                sin = Math.Sin(angle);
            }
            this.x += (int)(cos * this.v);
            this.y += (int)(sin * this.v);
        }

        public double gotoXYAndGetLen(int _x, int _y)
        {
            int dx = _x - this.x;
            int dy = _y - this.y;
            double len, sin, cos, angle;
            if (dx == 0)
            {
                cos = 0;
                sin = 1;
                if (dy < 0)
                    sin = -1;
            }
            else
            {
                len = Math.Sqrt(dy * dy + dx * dx);
                angle = Math.Acos(dx / len);
                if (dy < 0)
                    angle = -angle;
                cos = Math.Cos(angle);
                sin = Math.Sin(angle);
            }
            this.x += (int)(cos * this.v);
            this.y += (int)(sin * this.v);
            return (Math.Sqrt(cos * this.v * cos * this.v + sin * this.v * sin * this.v));
        }



        public double gotoObjectAndGetLen(Movable _obj)
        {
            int _x = _obj.getX();
            int _y = _obj.getY();
            return this.gotoXYAndGetLen(_x, _y);
        }

        public double getDistanceToObject(Movable _obj)
        {
            return Math.Sqrt((_obj.getX() - this.x) * (_obj.getX() - this.x) + (_obj.getY() - this.y) * (_obj.getY() - this.y));
        }

        public Boolean checkCollision(Rectangle _rectangle)
        {
            Rectangle myRectangle = this.getRectangle();
            return myRectangle.Intersects(_rectangle);
            
        }

        public Boolean checkInRect(int _x, int _y)
        {
            Rectangle myRectangle = this.getRectangle();
            return myRectangle.Intersects(new Rectangle(_x, _y, texture.Width, texture.Height));

        }

        public Boolean checkCollisionXLeft(Rectangle _rectangle)
        {
            int x = this.getRectangle().X + this.getRectangle().Width + 1;
            return (x >= _rectangle.X);

        }

        public Boolean checkCollisionXRight(Rectangle _rectangle)
        {
            int x = this.getRectangle().X - 1;
            return (x <= _rectangle.X + _rectangle.Width);
        }

        public Boolean checkCollisionYUp(Rectangle _rectangle)
        {
            int y = this.getRectangle().Y - 1;
            return (y <= _rectangle.Y + _rectangle.Height);
        }

        public Boolean checkCollisionYDown(Rectangle _rectangle)
        {
            int y = this.getRectangle().Y + 1;
            return (y >= _rectangle.Y);
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here

            base.Initialize();
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here


            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            // TODO: Add your drawing code here

            this.spriteBatch.Begin();
            this.spriteBatch.Draw(texture, new Vector2(this.x, this.y), null, Color.White, rotationAngle, origin, 1.0f, SpriteEffects.None, 0f);
            //this.spriteBatch.Draw(texture, new Vector2(this.x , this.y ), Color.White);
            this.spriteBatch.End();
            base.Draw(gameTime);
        }

        public void setX(int _x)
        {
            this.x = _x;
        }
        public void setY(int _y)
        {
            this.y = _y;
        }
        public void setTexture(Texture2D _texture)
        {
            this.texture = _texture;
        }

        public void setV(int _v)
        {
            this.v = _v;
        }

        public int getX()
        {
            return this.x;
        }

        public int getY()
        {
            return this.y;
        }

        public Texture2D getTexture()
        {
            return this.texture;
        }
        public int getV()
        {
            return this.v;
        }

        public Rectangle getRectangle()
        {
            return new Rectangle(this.x , this.y , this.texture.Width, this.texture.Height);
        }
        public Rectangle getRectangle(int x, int y)
        {
            return new Rectangle(x, y, this.texture.Width, this.texture.Height);
        }
        public void rotate(int x)
        {
            rotationAngle = (float)(Math.PI/180 * x);
        }
        public int getRotationAngle()
        {
            return (int)(rotationAngle * 180 / Math.PI); 
        }
    }
}
